#include "IOnvifTool.h"
#include <vector>
#include <string.h>
#include <unordered_map>
#include <thread>
#include <iostream>
using namespace std;
using std::string;

void func(const ONVIFTOOL_DEVICE_INFO *lpDeviceInfo, void *pUserData)
{
    auto p = (unordered_map<string, LPONVIFTOOL_VIDEO_CHANNEL_INFO> *)pUserData;

    // 释放之前的空间
    if (p->find(string(lpDeviceInfo->szServiceAddr)) != p->end())
    {
        memset((*p)[string(lpDeviceInfo->szServiceAddr)]->szChannelNameArray, 0, 50 * 300);
    }
    else
    {
        // 创建个新的结构体
        ONVIFTOOL_VIDEO_CHANNEL_INFO *channelInfo = new ONVIFTOOL_VIDEO_CHANNEL_INFO;
        // 保存信息
        p->insert(std::pair(string(lpDeviceInfo->szServiceAddr), channelInfo));
    }

    // 拷贝一份内容
    ONVIFTOOL_VIDEO_CHANNEL_INFO *channelInfo = (*p)[string(lpDeviceInfo->szServiceAddr)];
    channelInfo->byChannelSize = lpDeviceInfo->struChannelInfo.byChannelSize;
    for (int i = 0; i < channelInfo->byChannelSize; i++)
    {
        strcpy(channelInfo->szChannelNameArray[i], lpDeviceInfo->struChannelInfo.szChannelNameArray[i]);
    }
}

int main()
{
    vector<string> deviceAddr;                                                // 设备服务地址
    unordered_map<string, string> addrHandleMap;                              // map<设备服务地址, handle>
    unordered_map<string, LPONVIFTOOL_VIDEO_CHANNEL_INFO> addrChannelInfoMap; // map<设备服务地址, deviceInfo>

    // 开启服务
    ONVIFTOOL_Start(func, 0, &addrChannelInfoMap);

    // 设置间隔和日志
    ONVIFTOOL_SetAutoRequestInterval(0);
    ONVIFTOOL_SetLogToFile(0);

    for (auto iter : addrChannelInfoMap)
    {
        deviceAddr.push_back(iter.first);
    }

    // 主动添加设备
    deviceAddr.push_back("http://172.16.36.196/onvif/device_service");
    deviceAddr.push_back("http://172.16.34.91/onvif/device_service");
    deviceAddr.push_back("http://172.16.34.94/onvif/device_service");
    deviceAddr.push_back("http://172.16.34.73/onvif/device_service");
    deviceAddr.push_back("http://172.16.34.74/onvif/device_service");

    // 登录设备
    cout << "\n\n-----------login-----------\n\n"
         << endl;
    for (int i = 0; i < (int)deviceAddr.size(); i++)
    {
        if (deviceAddr[i] == "http://172.16.36.196/onvif/device_service" ||
            deviceAddr[i] == "http://172.16.34.91/onvif/device_service" ||
            deviceAddr[i] == "http://172.16.34.94/onvif/device_service" ||
            deviceAddr[i] == "http://172.16.34.73/onvif/device_service" ||
            deviceAddr[i] == "http://172.16.34.74/onvif/device_service")
        {
            char handle[100];

            if (ONVIFTOOL_Login(deviceAddr[i].c_str(), "admin2", "Tisson@123!", handle, 100) == false)
            {
                printf("%s login fail\n", deviceAddr[i].c_str());
                ONVIFTOOL_Stop();
                return 0;
            }
            addrHandleMap[deviceAddr[i]] = string(handle);
        }
    }

    // // 主动发送探测更新信息
    // cout << "\n\n-----------sendInquery-----------\n\n"
    //      << endl;
    // ONVIFTOOL_SendInquery();

    // 获取设备信息
    cout << "\n\n-----------getDevInfo-----------\n\n"
         << endl;
    for (int i = 0; i < (int)deviceAddr.size(); i++)
    {
        ONVIFTOOL_RET_GET_DEVICE_INFO_PARAM devInfo = {0};
        if (auto success = ONVIFTOOL_GetDeviceConfig(addrHandleMap[deviceAddr[i]].c_str(), ONVIFTOOL_GET_COMMAND_DEVICE_INFO,
                                                     nullptr, 0,
                                                     &devInfo, sizeof(ONVIFTOOL_RET_GET_DEVICE_INFO_PARAM));
            !success)
        {
            cout << "ONVIFTOOL_GetDeviceConfig error: serviceAddr: " << deviceAddr[i] << endl;
        }
        else
        {
            if (devInfo.iOnline == 0)
            {
                cout << deviceAddr[i] << " online : false" << endl;
                continue;
            }
            for (int j = 0; j < devInfo.iChannelSize; j++)
            {
                cout << "channelName: " << devInfo.szChannelNameArray[j]
                     << " online: " << ((devInfo.iChannelOnline[j] == 0) ? "false" : "true") << endl;
            }
        }
    }

    // 获取每个设备的两个码流URI
    cout << "\n\n-----------getStreamURI-----------\n\n"
         << endl;
    for (int i = 0; i < (int)deviceAddr.size() * 2; i++)
    {
        ONVIFTOOL_GET_STREAM_PARAM streamParam = {0};
        if (i % 2 == 0)
        {
            // 主码流
            streamParam.byStreamType = 0;
        }
        else
        {
            // 子码流
            streamParam.byStreamType = 1;
        }
        // UDP单播
        streamParam.byTransportType = 0;

        // 多个通道选最后那个
        streamParam.dwChannelNum = addrChannelInfoMap[deviceAddr[i / 2]]->byChannelSize;

        ONVIFTOOL_RET_GET_URI_PARAM streamResult = {0};
        if (auto success = ONVIFTOOL_GetDeviceConfig(addrHandleMap[deviceAddr[i / 2]].c_str(), ONVIFTOOL_GET_COMMAND_STREAM_URI,
                                                     &streamParam, sizeof(ONVIFTOOL_GET_STREAM_PARAM),
                                                     &streamResult, sizeof(ONVIFTOOL_RET_GET_URI_PARAM));
            !success)
        {
            cout << "ONVIFTOOL_GetDeviceConfig error: serviceAddr: " << deviceAddr[i / 2] << endl;
        }
        else
        {
            cout << "URI:" << streamResult.URI << endl;
        }
    }

    // 修改通道名
    cout << "\n\n-----------modChannelName-----------\n\n"
         << endl;
    ONVIFTOOL_SET_CHANNEL_PARAM setChannel = {0};
    setChannel.dwChannelNum = 2;
    strcpy(setChannel.szChannelName, "云台通道qefc");

    if (auto success = ONVIFTOOL_SetDeviceConfig(addrHandleMap["http://172.16.34.91/onvif/device_service"].c_str(), ONVIFTOOL_SET_COMMAND_CHANNEL_NAME,
                                                 &setChannel, sizeof(ONVIFTOOL_SET_CHANNEL_PARAM),
                                                 nullptr, 0);
        !success)
    {
        cout << "ONVIFTOOL_SET_COMMAND_CHANNEL_NAME error" << endl;
    }

    // 获取抓图uri
    cout << "\n\n-----------getSnapShotURI-----------\n\n"
         << endl;
    ONVIFTOOL_GET_SNAPSHOT_PARAM snapShotParam = {0};
    snapShotParam.dwChannelNum = 2;
    ONVIFTOOL_RET_GET_URI_PARAM snapShotResult = {0};

    if (auto success = ONVIFTOOL_GetDeviceConfig(addrHandleMap["http://172.16.36.196/onvif/device_service"].c_str(), ONVIFTOOL_GET_COMMAND_SNAPSHOT_URI,
                                                 &snapShotParam, sizeof(ONVIFTOOL_GET_SNAPSHOT_PARAM),
                                                 &snapShotResult, sizeof(ONVIFTOOL_RET_GET_URI_PARAM));
        !success)
    {
        cout << "ONVIFTOOL_GET_COMMAND_STREAM_URI error" << endl;
    }
    else
    {
        cout << "snapShot URI:" << snapShotResult.URI << endl;
    }

    // // 重启设备
    // cout << "\n\n-----------rebootDevice-----------\n\n" << endl;
    // if (auto success = ONVIFTOOL_SetDeviceConfig(addrHandleMap["http://172.16.36.196/onvif/device_service"].c_str(), ONVIFTOOL_SET_COMMAND_REBOOT,
    //                                              nullptr, 0,
    //                                              nullptr, 0);
    //     !success)
    // {
    //     cout << "ONVIFTOOL_SET_COMMAND_REBOOT error" << endl;
    // }

    // 获取回看列表
    cout << "\n\n-----------getRecordList-----------\n\n"
         << endl;
    ONVIFTOOL_GET_RECORD_LIST_PARAM recordParam = {0};
    recordParam.dwChannelNum = 3;
    recordParam.byIndex = 0;
    strcpy(recordParam.szBeginTime, (const char *)"2024-01-01 00:00:00");
    strcpy(recordParam.szEndTime, (const char *)"2024-01-08 23:00:00");
    ONVIFTOOL_RET_GET_RECORD_LIST_PARAM recordResult = {0};

    if (auto success = ONVIFTOOL_GetDeviceConfig(addrHandleMap["http://172.16.34.74/onvif/device_service"].c_str(), ONVIFTOOL_GET_COMMAND_RECORD_LIST,
                                                 &recordParam, sizeof(ONVIFTOOL_GET_RECORD_LIST_PARAM),
                                                 &recordResult, sizeof(ONVIFTOOL_RET_GET_RECORD_LIST_PARAM));
        !success)
    {
        cout << "ONVIFTOOL_GET_COMMAND_RECORD_LIST error" << endl;
    }
    else
    {
        cout << "record list:" << endl;
        cout << "list size:" << (int)recordResult.byListSize << endl;
        for (int i = 0; i < (int)recordResult.byListSize; i++)
        {
            cout << "recordName: " << recordResult.szRecordName[i] << endl;
            cout << "startTime: " << recordResult.szStartTime[i] << endl;
            cout << "stopTime: " << recordResult.szStopTime[i] << endl;
        }
        cout << "has more:" << ((int)recordResult.byMore == 0 ? "false" : "true") << endl;
    }
    if (recordResult.byListSize > 0)
    {
        // 获取回看URI
        ONVIFTOOL_GET_RECORD_URI_PARAM recordURIParam = {0};
        recordURIParam.byTransportType = 0;
        strcpy(recordURIParam.szRecordName, recordResult.szRecordName[0]);
        ONVIFTOOL_RET_GET_URI_PARAM recordURIResult = {0};

        if (auto success = ONVIFTOOL_GetDeviceConfig(addrHandleMap["http://172.16.34.74/onvif/device_service"].c_str(), ONVIFTOOL_GET_COMMAND_RECORD_URI,
                                                     &recordURIParam, sizeof(ONVIFTOOL_GET_RECORD_URI_PARAM),
                                                     &recordURIResult, sizeof(ONVIFTOOL_RET_GET_URI_PARAM));
            !success)
        {
            cout << "ONVIFTOOL_GET_COMMAND_RECORD_URI error" << endl;
        }
        else
        {
            cout << "record URI :" << recordURIResult.URI << endl;
        }
    }

    // PTZ控制右
    cout << "\n\n-----------PTZ-----------\n\n"
         << endl;
    ONVIFTOOL_SET_PTZ_PARAM ptzParam = {0};
    ptzParam.dwChannelNum = 2;
    ptzParam.byAction = 0;
    ptzParam.byCommand = 1;
    ptzParam.speed = 0.2;

    if (auto success = ONVIFTOOL_SetDeviceConfig(addrHandleMap["http://172.16.34.91/onvif/device_service"].c_str(), ONVIFTOOL_SET_COMMAND_PTZ,
                                                 &ptzParam, sizeof(ONVIFTOOL_SET_PTZ_PARAM),
                                                 nullptr, 0);
        !success)
    {
        cout << "ONVIFTOOL_SET_COMMAND_PTZ right error" << endl;
    }
    else
    {
        cout << "right success" << endl;
    }
    this_thread::sleep_for(chrono::seconds(5));

    // PTZ控制右上
    ptzParam.byCommand = 6;

    if (auto success = ONVIFTOOL_SetDeviceConfig(addrHandleMap["http://172.16.34.91/onvif/device_service"].c_str(), ONVIFTOOL_SET_COMMAND_PTZ,
                                                 &ptzParam, sizeof(ONVIFTOOL_SET_PTZ_PARAM),
                                                 nullptr, 0);
        !success)
    {
        cout << "ONVIFTOOL_SET_COMMAND_PTZ right_up error" << endl;
    }
    else
    {
        cout << "right_up success" << endl;
    }
    this_thread::sleep_for(chrono::seconds(5));

    // PTZ控制停止
    ptzParam.byAction = 1;

    if (auto success = ONVIFTOOL_SetDeviceConfig(addrHandleMap["http://172.16.34.91/onvif/device_service"].c_str(), ONVIFTOOL_SET_COMMAND_PTZ,
                                                 &ptzParam, sizeof(ONVIFTOOL_SET_PTZ_PARAM),
                                                 nullptr, 0);
        !success)
    {
        cout << "ONVIFTOOL_SET_COMMAND_PTZ stop error" << endl;
    }
    else
    {
        cout << "stop success" << endl;
    }

    // PTZ控制focus_near
    ptzParam.byAction = 0;
    ptzParam.byCommand = 10;
    if (auto success = ONVIFTOOL_SetDeviceConfig(addrHandleMap["http://172.16.34.91/onvif/device_service"].c_str(), ONVIFTOOL_SET_COMMAND_PTZ,
                                                 &ptzParam, sizeof(ONVIFTOOL_SET_PTZ_PARAM),
                                                 nullptr, 0);
        !success)
    {
        cout << "ONVIFTOOL_SET_COMMAND_PTZ focus_near error" << endl;
    }
    else
    {
        cout << "focus_near success" << endl;
    }
    this_thread::sleep_for(chrono::seconds(5));

    // PTZ控制focus_far
    ptzParam.byAction = 0;
    ptzParam.byCommand = 11;
    if (auto success = ONVIFTOOL_SetDeviceConfig(addrHandleMap["http://172.16.34.91/onvif/device_service"].c_str(), ONVIFTOOL_SET_COMMAND_PTZ,
                                                 &ptzParam, sizeof(ONVIFTOOL_SET_PTZ_PARAM),
                                                 nullptr, 0);
        !success)
    {
        cout << "ONVIFTOOL_SET_COMMAND_PTZ focus_far error" << endl;
    }
    else
    {
        cout << "focus_far success" << endl;
    }
    this_thread::sleep_for(chrono::seconds(5));

    // PTZ控制停止
    ptzParam.byAction = 1;

    if (auto success = ONVIFTOOL_SetDeviceConfig(addrHandleMap["http://172.16.34.91/onvif/device_service"].c_str(), ONVIFTOOL_SET_COMMAND_PTZ,
                                                 &ptzParam, sizeof(ONVIFTOOL_SET_PTZ_PARAM),
                                                 nullptr, 0);
        !success)
    {
        cout << "ONVIFTOOL_SET_COMMAND_PTZ stop error" << endl;
    }
    else
    {
        cout << "stop success" << endl;
    }

    // // 获取预置位信息
    // cout << "\n\n-----------Preset-----------\n\n" << endl;
    // ONVIFTOOL_PRESET_PARAM presetParam = {0};
    // presetParam.byCommand = 0;
    // presetParam.byIndex = 0;
    // presetParam.dwChannelNum = 1;
    // presetParam.dwPresetIndex = 0;
    // memset(presetParam.szPresetName, 0, sizeof(presetParam.szPresetName));

    // ONVIFTOOL_RET_PRESET_PARAM presetResult = {0};

    // if (auto success = ONVIFTOOL_GetDeviceConfig(addrHandleMap["http://172.16.34.94/onvif/device_service"].c_str(), ONVIFTOOL_GET_COMMAND_PRESETS,
    //                                              &presetParam, sizeof(ONVIFTOOL_PRESET_PARAM),
    //                                              &presetResult, sizeof(ONVIFTOOL_RET_PRESET_PARAM));
    //     !success)
    // {
    //     cout << "ONVIFTOOL_GET_COMMAND_PRESETS search error" << endl;
    // }
    // else
    // {
    //     cout << "search preset success" << endl;
    //     cout << "preset Size: " << presetResult.dwListSize << endl;
    //     cout << "has more preset: " << (presetResult.byMore == 0 ? "false" : "true") << endl;
    //     for (int i = 0; i < (int)((int)presetResult.dwListSize > 20 ? 20 : presetResult.dwListSize); i++)
    //     {
    //         cout << "preset index:" << presetResult.dwPresetIndex[i] << endl;
    //         cout << "preset name:" << presetResult.szPresetName[i] << endl;
    //     }
    // }

    // // 添加预置位
    // presetParam.byCommand = 1;
    // presetParam.dwPresetIndex = 455;
    // strcpy(presetParam.szPresetName, "wzj_presetName");
    // memset(&presetResult, 0, sizeof(ONVIFTOOL_RET_PRESET_PARAM));
    // if (auto success = ONVIFTOOL_SetDeviceConfig(addrHandleMap["http://172.16.34.94/onvif/device_service"].c_str(), ONVIFTOOL_SET_COMMAND_PRESET,
    //                                              &presetParam, sizeof(ONVIFTOOL_PRESET_PARAM),
    //                                              &presetResult, sizeof(ONVIFTOOL_RET_PRESET_PARAM));
    //     !success)
    // {
    //     cout << "ONVIFTOOL_SET_COMMAND_PRESET add error" << endl;
    // }
    // else
    // {
    //     cout << "add preset success" << endl;
    //     cout << "preset Size: " << presetResult.dwListSize << endl;
    //     cout << "has more preset: " << (presetResult.byMore == 0 ? "false" : "true") << endl;
    //     for (int i = 0; i < (int)((int)presetResult.dwListSize > 20 ? 20 : presetResult.dwListSize); i++)
    //     {
    //         cout << "preset index:" << presetResult.dwPresetIndex[i] << endl;
    //         cout << "preset name:" << presetResult.szPresetName[i] << endl;
    //     }
    // }

    // // 编辑预置位
    // presetParam.byCommand = 3;
    // memset(&presetResult, 0, sizeof(ONVIFTOOL_RET_PRESET_PARAM));
    // if (auto success = ONVIFTOOL_SetDeviceConfig(addrHandleMap["http://172.16.34.94/onvif/device_service"].c_str(), ONVIFTOOL_SET_COMMAND_PRESET,
    //                                              &presetParam, sizeof(ONVIFTOOL_PRESET_PARAM),
    //                                              &presetResult, sizeof(ONVIFTOOL_RET_PRESET_PARAM));
    //     !success)
    // {
    //     cout << "ONVIFTOOL_SET_COMMAND_PRESET edit error" << endl;
    // }
    // else
    // {
    //     cout << "edit preset success" << endl;
    //     cout << "preset Size: " << presetResult.dwListSize << endl;
    //     cout << "has more preset: " << (presetResult.byMore == 0 ? "false" : "true") << endl;
    //     for (int i = 0; i < (int)((int)presetResult.dwListSize > 20 ? 20 : presetResult.dwListSize); i++)
    //     {
    //         cout << "preset index:" << presetResult.dwPresetIndex[i] << endl;
    //         cout << "preset name:" << presetResult.szPresetName[i] << endl;
    //     }
    // }

    // // 删除预置位
    // presetParam.byCommand = 2;
    // memset(&presetResult, 0, sizeof(ONVIFTOOL_RET_PRESET_PARAM));
    // if (auto success = ONVIFTOOL_SetDeviceConfig(addrHandleMap["http://172.16.34.94/onvif/device_service"].c_str(), ONVIFTOOL_SET_COMMAND_PRESET,
    //                                              &presetParam, sizeof(ONVIFTOOL_PRESET_PARAM),
    //                                              &presetResult, sizeof(ONVIFTOOL_RET_PRESET_PARAM));
    //     !success)
    // {
    //     cout << "ONVIFTOOL_SET_COMMAND_PRESET delete error" << endl;
    // }
    // else
    // {
    //     cout << "delete preset success" << endl;
    //     cout << "preset Size: " << presetResult.dwListSize << endl;
    //     cout << "has more preset: " << (presetResult.byMore == 0 ? "false" : "true") << endl;
    //     for (int i = 0; i < (int)((int)presetResult.dwListSize > 20 ? 20 : presetResult.dwListSize); i++)
    //     {
    //         cout << "preset index:" << presetResult.dwPresetIndex[i] << endl;
    //         cout << "preset name:" << presetResult.szPresetName[i] << endl;
    //     }
    // }

    // // goto 预置位
    // if (presetResult.dwListSize > 0)
    // {
    //     presetParam.byCommand = 4;
    //     presetParam.dwPresetIndex = presetResult.dwListSize; // goto最后一个有效的preset

    //     if (auto success = ONVIFTOOL_SetDeviceConfig(addrHandleMap["http://172.16.34.94/onvif/device_service"].c_str(),
    //                                                  ONVIFTOOL_SET_COMMAND_PRESET,
    //                                                  &presetParam, sizeof(ONVIFTOOL_PRESET_PARAM),
    //                                                  &presetResult, sizeof(ONVIFTOOL_RET_PRESET_PARAM));
    //         !success)
    //     {
    //         cout << "ONVIFTOOL_SET_COMMAND_PRESET goto error" << endl;
    //     }
    //     else
    //     {
    //         cout << "goto success" << endl;
    //     }
    // }

    ONVIFTOOL_Stop();
}